Rotate object's mesh so it matches another object's rotation Suppose we have two cube objects: Obj1 and Obj2. Let's say Obj1's Euler rotation is Vector((0,0,0)) and Obj2's rotation is Vector((0,0,45)) How can I rotate Obj1's mesh so that it matches Obj2's rotation? I know that BMesh lets me rotate vertices of an object but I don't know how to implement it properly. I tried this and it didn't work:

import bpy
import mathutils
from mathutils import  Quaternion, Vector, Matrix
import bmesh
import math
from math import radians

context = bpy.context
data = bpy.data

obj1 = data.objects['Obj1']
obj2 = data.objects['Obj2']

from_quat_rot = obj1.rotation_quaternion
to_quat_rot = obj2.rotation_quaternion

difference_quat = from_quat_rot.rotation_difference(to_quat_rot)
difference_angle = difference_quat.angle

print(f"difference quaternion: {difference_quat}")
print(f"difference angle: {difference_angle}")


vector_zero = Vector((0, 0, 0))
bm = bmesh.new()
bm.from_mesh(obj1.data)
#bmesh.ops.rotate(bm, cent=vector_zero, verts=bm.verts, matrix=Matrix.Rotation(radians(difference_angle), 4, 'Z'))
bmesh.ops.rotate(bm, cent=vector_zero, verts=bm.verts, matrix=difference_quat.to_matrix())
bm.to_mesh(obj1.data)
bm.free()


Unfortunately I don't know linear algebra so I probably won't understand if you provide me with an equation, I'd rather prefer a bit of python code. Thanks.
If your objects are in Euler rotation mode, then the quaternion wont be set. For any mode using

ob.matrix_world.to_euler()
ob.matrix_world.to_quaternion()


will give the global euler and quaternion rotation respectively.

import bpy
import mathutils
from mathutils import  Quaternion, Vector, Matrix
import bmesh
import math
from math import radians

context = bpy.context
data = bpy.data

obj1 = data.objects['Cube']
obj2 = data.objects['Cube.001']

from_quat_rot = obj1.matrix_world.to_quaternion()
to_quat_rot = obj2.matrix_world.to_quaternion()
from_euler_rot = obj1.rotation_euler
to_euler_rot = obj2.rotation_euler

difference_quat = from_quat_rot.rotation_difference(to_quat_rot)
difference_angle = difference_quat.angle

print(f"difference angle: {difference_angle}")

vector_zero = Vector((0, 0, 0))
bm = bmesh.new()
bm.from_mesh(obj1.data)
bmesh.ops.rotate(bm, 
        cent=vector_zero, 
        verts=bm.verts, 
        matrix=Matrix.Rotation(difference_angle, 4, difference_quat.axis))
bm.to_mesh(obj1.data)
bm.free()


This rotates the mesh as expected.  Running again will have an accumulative effect.

could also

M = difference_quat.to_matrix()
obj1.data.transform(M)
obj1.data.update()