You only have to define a texture tag inside the material definition if you want a texture to be bound to a slot automatically when the resource is loaded. You can still call Material::SetTexture to explicitly bind a texture to a material, even one you created by loading an XML definition. Even if you do assign a texture inside the material XML, you can still override/overwrite it using SetTexture.
You setup your XML so that it specifies all the settings you need: cull mode, technique, passes, etc… Load it via ResourceCache::GetResource, then with the returned pointer you call SetTexture to set your texture to the appropriate slot. Then you can assign that Material pointer to as many models as you need.
Since ResourceCache is now managing the lifetime of your Material, you can call GetResource with the name of your material at any time to obtain another pointer to the same material instance. Then you can call Material::SetTexture on this pointer to change the bound texture for all instances of that material, meaning that you can perform whatever Tile initialization and construction you need to do simply by calling tileObject->SetMaterial, then after the fact or during runtime you can change the bound texture by obtaining another pointer to the Material from the cache.
Note that in this pattern, since all Tiles share a material instance, changing the texture bound to one will change the texture bound to all. If you do have Tiles that need a different texture, you will have to create separate Material instances for each texture.