Well, I gave it a shot, but all I could manage was to rotate entire selection by whatever angle (value) is used. I am not iterating over individual meshes. If somebody can tweak this, I'm sure it would work:
from datetime import datetime
for obj in bpy.context.selected_objects:
randnum = math.radians(90 * random.randint(0,3))
bpy.ops.transform.rotate(value=randnum, orient_axis='Z', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
Change 90 to 45 and you will see what I mean. Scripts are accessible in 2.8 from the Scripting tab.
EDIT: Actually , selecting each panel one at a time, hovering the cursor over the script panel, and pressing "ALT"+"P" (which runs the script on the selected tile) takes less than a second. Doing this with each of these hundred panels took less than 100 seconds. The result looks like what you want and the time is reasonable if you want to tile a hundred or fewer panels on a wall:
Note: You will see if you open the .blend file, but each of these tiles is a copy of a scaled down cube with two vertices moved down slightly. This ensures the back of the tiles are flush with the wall. You can move them down further (or the other two up) if you want a more dramatic slope. But you will need to delete the other 99 and generate, then apply the arrays again. That will only take a few seconds though.