I'm not really sure, honestly. There are several different concepts at play here:
1) Blocks that differ by quantity - example: single bookcase block that may represent the number of books in it (no distribution, single block)
2) Blocks that could use variety breaks shuffled randomly - example: dirt, grass, etc, could be done with the Wang Tiles concept to distribute in a purely programmatic fashion (equally distributed over any size area)
3) Blocks that break monotony occasionally - example: single brick blocks in an otherwise seamless brick wall that just shows damage, plant growth, etc (distribution heavily favors the single "normal" brick block)
4) Blocks that break monotony specifically - example: an old building that has a large patch of wall replaced with a new style brick (distribution has a clean break between old and new bricks)
Thinking about how those could work / be classified - simplified setup assuming we go all out on unique block IDs rather than use sneaky tricks
1) Bookcase example. The extra textures are meant to rotate through a quantity on a single block. Easy - make each a unique block (Bookcase1, Bookcase2, etc) and have the code change the active block picked based on quantity
One drawback with making bookcases functional - great for the player who wants to place a bookcase in a house with actual books in it. But generating structures in the world that contain bookcases - do you attempt to generate actual books, or just inactive bookcases that don't actually hold real books? Can the player only create empty bookcases, then must seek out or create actual books? If there are both inactive and active bookcases you might want some other bookcase textures, say for ruined books, since it would make some sense that you can't interact with those. Maybe RuinedBookcase. Inactive bookcases might just pick a quantity-based block at random
2) Random distribution - there are sort of two related concepts here, a random choice and an animated block. Water blocks actually use a 16x?? pixel PNG strip and just animates by switching the second axis up and down the strip.
I wonder if you could do something similar for blocks that may change, like grass and dirt - simply include a larger PNG strip with the variations and have the engine pick one and stick with it. Which may be tricky as each reload would have to re-pick, so your random distribution shuffles between world reloads, which might look funny. So still might need unique blocks per variety, but the engines needs to pick one at random instead of relating it to quantity
3) This might be the trickiest - although you could just have the engine occasionally output a random sub-variety of a parent type. So you place a ton of YellowBricks to make a wall, and every 20th brick randomly picks a YellowBrickVar1, YellowBrickVar2, etc, where one might have some moss on it, one may have a cracked brick, etc. For player-placed walls maybe all bricks start out pristine, and over time occasionally one gets replaced with a variant (moss grew on it, a brick cracked, etc)
4) Differing bricks not placed randomly (need to match in multi-block segments) - pretty much need unique brick blocks here. Engine could possibly generate a wall made of different types. So could players. So not really a variation choice, instead just RedBrick, YellowBrick, DarkYellowBrick, etc.
In addition to that you might have outright ruined blocks, like a partial brick wall. They'd also be fully unique blocks. Heck, the more I think and write about it the more it makes sense to just go easy and make everything unique blocks, bloating the heck out of the total number of block IDs
So if you were to do Bookcase textures that would fit well with B!0HAX's quantity-based bookcases I'd go with either a similar set of 16 in a different material, or just one-off ruined / non-interactive bookcases
At some point tho we'll probably have too many bookcases
