You can use shapely.ops.nearest_points
Returns a tuple of the nearest points in the input geometries. The
points are returned in the same order as the input geometries.
If you have many polygons you can sjoin_nearest each polygon to the points. I only have one:
import geopandas as gpd
import shapely
#Create a polygon df with one row
polygon_wkt = r'Polygon ((4.68817446043166264 25.336443345323719, 5.96762589928058151 25.83217176258990477, 7.03666502143541095 24.97199852227128147, 6.82625270474132062 23.6160968646864724, 5.54680126589240086 23.12036844742028663, 4.47776214373757142 23.98054168773890993, 4.68817446043166264 25.336443345323719))'
polygon_geometry = [shapely.wkt.loads(polygon_wkt)]
polydf = gpd.GeoDataFrame(geometry=polygon_geometry, crs=4326)
#Create a point df with some random points inside the polygon
point_geometries = list(polydf.sample_points(size=20).iloc[0].geoms)
pointdf = gpd.GeoDataFrame(geometry=point_geometries, crs=4326)
#For each point, find the nearest point on the polygon border using shapely.ops.nearest_points
pointdf["nearest_polypoint"]= pointdf.geometry.apply(
lambda x: shapely.ops.nearest_points(g1=x, g2=polydf.iloc[0].geometry.boundary)[1])
# pointdf.head(2)
# geometry nearest_polypoint
# 0 POINT (4.68303 24.42042) POINT (4.54925 24.44119)
# 1 POINT (4.76674 24.10765) POINT (4.50382 24.14845)
#Create a line df of the point pairs in pointdf
shortest_lines = pointdf.apply(lambda x: shapely.LineString([x.geometry, x.nearest_polypoint]), axis=1)
linedf = gpd.GeoDataFrame(geometry=shortest_lines, crs=4326)
#Plot
ax = polydf.plot(figsize=(10,10), color="lightyellow", edgecolor="black")
pointdf.plot(ax=ax, color="blue")
linedf.plot(ax=ax, color="magenta")