Rotate object on local axis using a slider
By using obj.matrix_world *= Matrix(...) you apply the rotation on top of the existing matrix, which explains the behaviour you're seeing.

Rather than changing the matrix, why not go to the source of the rotation itself, the rotation_euler property? You can just do obj.rotation_euler.z = radians(self["rotate"]) and let Blender to do the matrix math for you.

Alternatively you could use a driver that reads that particular window manager property.