Is it good practice to use all the available texture units?
Modern hardware doesn't really have the concept of texture binding points as exposed by OpenGL. Rather, the shader unit uses a descriptor (which is just some kind of fat pointer) which can potentially address any texture as long as it's resident in video memory. This is what makes things like bindless textures possible. So the large amount of "texture units" available in current implementations is simply trying to handwave this now-irrelevant part of the API.

That said, the recommended way of implementing what you're trying to do (avoiding re-binding of textures) is to use texture arrays, which allow you to dynamically index into a set of textures in the shader, as long as they all have the same format and size. This presentation contains more details about these and other techniques for reducing driver overhead when rendering with modern OpenGL: Approaching Zero Driver Overhead