I understand the concepts of name-based virtual hosts (i.e. serving two domain names differently) and ip-based virtual hosts (i.e. a serving two ip's differently)
But...
Should I always specify an IP address, or is it OK to use *? Many examples of name-based virutal hosting still specify IP addresses. Why is VirtualHost a block and NameVirtualHost a directive? Why do I need NameVirtualHost for IP-based virtual hosts?
You can specify * in both directives.
NameVirtualHost only defines IP on which you'll use name virtual hosts. Doesn't contain other directives, so no reason why it should be block. On the other hand VirtualHost does contain other directives for particular virtual host, so it has to be a block.
You don't need it. See example.
Recommended reading: Apache Virtual Host documentation