I've been working on code that uses Z buffering for the blocks too, using some trickery to avoid Z-fighting. Namely, when each face is drawn, the Z buffer is read to determine where to draw as usual, but it's not written to. Thus, multiple graphics on the same face won't Z-fight, and which one is in front is determined by rendering order. Then, after this, it draws them again in a second pass, this time *only* writing the Z buffer (but not drawing the actual pixels).
This somewhat works (and eliminates the remaining issues with the current code), but Z-fighting can still occur in some cases, such as if we have two blocks next to each other A B where both the right face of A, and the left face of B, have a graphic to draw (due to one having a double-sided graphic on that face). To address this, I need to modify the code to handle paired faces together. Not too hard to do in and of itself, but a bit trickier to optimize - my initial attempts at this method of rendering the blocks had utterly awful frame rates, but I managed to hugely optimize it; the existing optimization wouldn't work well when working with pairs of faces, so I'd need to find another way.