For Unity users (or anyone writing shaders for custom engines), the trick is to rotate the x and y of the tangent Normal with the opposite rotation. This means calculating a second rotation matrix with the inverse angle, or the inverse matrix. However with basic rotation matrices with no (or uniform) scale, the transpose matrix is the same as the inverse, and that’s much easier to calculate. Easier still, just using a different order of the matrix and vector will apply the matrix as the transpose.
HLSL example:
// Get sine and cosine for angle (in degrees)
float s, c;
sincos(_Angle * (3.14159265 / 180.0), s, c);
// Construct rotation matrix from sine and cosine
float2x2 UVRotationMatrix = float2x2(c,-s,
s, c);
// Apply rotation to UV, centered around UV (0.5, 0.5)
float2 rotatedUV = mul(UVRotationMatrix, IN.uv - float2(0.5, 0.5)) + float2(0.5, 0.5);
// Get vector from normal map
half3 normal = UnpackNormal(tex2D(_BumpMap, rotatedUV));
// Rotate vector back into the original tangent space with transposed rotation
normal.xy = mul(normal.xy, UVRotationMatrix);