#05AB1E, 41 bytes
gUεN©Āiø¹®<èøJC‚øε`._}ø}NX<Êi¹®>èJC‚øε`._
This feels way too long.. Can definitely be golfed some more.
Try it online or verify all test cases.
Explanation:
g # Get the length (amount of layers) of the (implicit) input
U # Pop and store it in variable `X`
ε # Map each layer in the (implicit) input to:
N© # Push the layer-index, and store it in the register (without popping)
Āi # If it is not the first layer:
ø # Zip/transpose the current layer; swapping rows/columns
¹®<è # Get the `N-1`'th layer of the input
ø # Zip/transpose; swapping rows/columns
J # Join all inner lists (the columns) together
C # And convert it from binary to integer
‚ # Pair it with the current layer's columns we're mapping
ø # Zip/transpose; to pair each integer with a layer's columns
ε } # Map over these pairs:
` # Push both values of the pair separately to the stack
._ # Rotate the column the integer amount of times
ø # Zip/transpose the rows/columns of the current layer back
} # Close the if-statement
NX<Êi # If this is not the last layer (layer-index != amount_of_layers):
¹®>è # Get the `N+1`'th layer of the input
J # Join all inner lists (the rows) together
C # And convert it from binary to integer
‚ # Pair it with the current layer's rows we're mapping
ø # Zip/transpose; to pair each integer with a layer's rows
ε # Map over these pairs:
` # Push both values of the pair separately to the stack
._ # Rotate the row the integer amount of times
# (implicitly output the result after the layer-mapping is done)