There are a few directions you could go with this. It'll depend on the infrastructure you have in place, and the software you're willing to pay for and/or deploy.
What's the purpose of having so many separate build machines? Is it to keep code projects isolated from each other, or to maximise build speed with additional resources? Or are the build machines actually the client workstations on your network, which are used for additional purposes other than building?
If it's to keep the build environments isolated, then virtualisation is a good route to persue. You'll be able to raise your 20 build machines as individual VMs without the extra hassle of purchasing/configuring hardware for each one.
On the other hand if it's for performance scaling, bundling the build machines onto VMs doesn't make as much sense since VMs on a host contend for that host's CPU, RAM and disk availability. You're better off adding the max amount of CPU cores, Gbs RAM, and disk spindles as required by adding additional units of hardware.
As for the requirement to update software packages across all machines:
- For unified software management across a number of Windows machines without requiring a re-deployment of the OS, check out Microsoft's System Center Config Manager, and System Center Essentials. They sound about right for your requirements: http://www.microsoft.com/systemcenter/en/us/products.aspx
- For whole-system deployment where you'd make a change to a system 'image', then re-deploy that image out to your build machines, you can do this with VMs using features built into whichever virtualisation product you're using - 'Templates' on ESX or Hyper-V. Alternatively, you could look at a PXE-boot build solution like Windows Deployment services.
Whichever way you go with this, your biggest pain-point is likely to be the mixed use of Windows and MacOS for your build machines. A standard OS across all of them is pretty much a pre-requisite for being able to update them all in a unified manner.