to achieve such a goal you have to split the question to smaller sub steps, for example:
- Split a UV (or XY) coordinate to a grid by using the Fraction or Modulo Operator.
- Modify each grid cell local UV with a random translation
- To gain randomness there are some mathematical combinations that generate pseudo random behavior, but each input will always generate the same output. Therefore i convert a common shader function to a node group:
float N21(in vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * .1031);
p3 += dot(p3, p3.yzx + 33.33);
return fract((p3.x + p3.y) * p3.z);
}

- Calculate the distance to the border of the modified cell to create a "mortar-mask"
- Combine each cell by calculating "which cell is at this pixel" by using Greater or Less than, Multiply or Adding Values. It often helps by keeping all values in a 0 to 1 range.

In the end you get different masks and UV coordinates which can be colorized with normal image textures to get the marble look.
It may help to use a tool like Shadertoy (Example of my wall texture algorithm) to test a algorithm and convert it to node groups after you are satisfied with the result.
You could use my blend file as a library to link or attach the node groups. Try to modify some values to see the result.
Getting good looking procedural textures is heavy math!
Have fun and greetings from Germany!