Option 1
you can simply use angle parameter in patches.Rectangle:
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
import numpy as np
from skimage import data, io, filters
im = np.array(data.coins(), dtype=np.uint8)
# Create figure and axes
fig,ax = plt.subplots(1)
# Display the image
ax.imshow(im)
# Create a Rectangle patch
rect = patches.Rectangle((50,100),100,80,linewidth=1,edgecolor='r',facecolor='none')
rect_2 = patches.Rectangle((50,100),100,80,linewidth=1,edgecolor='r',facecolor='none', angle=30)
# Add the patch to the Axes
ax.add_patch(rect)
ax.add_patch(rect_2)
plt.show()

Option 2
Or if you want to do this in a mathematical way, use a rotation matrix. I just show you how can calculate the corner points of your rotated box
Previous corner points

First I set up the unrotated points:
x = [101,101,270, 270]
y = [27, 388, 27,388]
Now we create the rotation matrix
rot_mat = np.array([[np.cos(pi/6), -np.sin(pi/6)], [ np.sin(pi/6), np.cos(pi/6)]])
Now we centralize x and y, by shifting them (so that center of the rectangle is equivalent to the origin)
x_cen = np.array(x) - np.mean(x)
y_cen = np.array(y) -np.mean(y)
Apply the rotation matrix to the centralized arrays and shift back
x_rot = np.dot(rot_mat, np.array((x_cen,y_cen)))[0,:] + np.mean(x)
y_rot = np.dot(rot_mat, np.array((x_cen,y_cen)))[1,:] + np.mean(x)
Rotated corner points:
