Taming Resource Heterogeneity In Distributed ML Training With Dynamic Batching