Good grief, who is modelling all these? Surely you mean 160 -- not 16,000?
16k draw calls [...] 321 meshes and 386 textures.
Ah OK, that is much more like it.
[screenshot]
That is a ton of draw calls for what I see. Are you planning to do any culling and/or instancing?
Yes indeed. This looks like approx. 13,900 of the 14,000 drawn meshes are grass and shrubs.
You should really consider array textures, instancing, and indirect draw calls if there is any possibility. Since a really old graphics card probably won't be able to handle that amount of overdraw anyway, you should have it available on your target hardware.
Array textures alone can probably reduce the number of state changes to like 5-10% of what it is now. Assuming the minimum guaranteed supported number of layers (256), you would need a maximum two array textures, assuming that you reference each and every texture that exists in your pool (which likely won't be the case!).
Even without indirect draws and not using instancing, you could batch draw calls together considerably, just not as efficiently. In the easiest case, you could write 100 or 200 of those shrubs into a dynamic vertex (well, ... index) buffer object at a time, and use primitive restart to separate them. That's pretty poor performance-wise but probably still much faster than doing thousands of draw calls for thousands of 20-vertex meshes.
Of course, using instancing for something that totally begs for instancing would be preferrable (same for indirect calls). Really, this is what instancing was made for.