You can also write Shapely geometries by using PyShp (since the original poster also asked about PyShp).

One way would be to convert your shapely geometry to geojson (with the shapely.geometry.mapping method) and then use [my modified fork of PyShp][1] which provides a Writer method that accepts geojson geometry dictionaries when writing to a shapefile. 

If you would rather rely on the main PyShp version, I have also provided a conversion function below:

    # THIS FUNCTION CONVERTS A GEOJSON GEOMETRY DICTIONARY TO A PYSHP SHAPE OBJECT
    def shapely_to_pyshp(shapelygeom):
        # first convert shapely to geojson
        try:
            shapelytogeojson = shapely.geometry.mapping
        except:
            import shapely.geometry
            shapelytogeojson = shapely.geometry.mapping
        geoj = shapelytogeojson(shapelygeom)
        # create empty pyshp shape
        record = shapefile._Shape()
        # set shapetype
        if geoj["type"] == "Null":
            pyshptype = 0
        elif geoj["type"] == "Point":
            pyshptype = 1
        elif geoj["type"] == "LineString":
            pyshptype = 3
        elif geoj["type"] == "Polygon":
            pyshptype = 5
        elif geoj["type"] == "MultiPoint":
            pyshptype = 8
        elif geoj["type"] == "MultiLineString":
            pyshptype = 3
        elif geoj["type"] == "MultiPolygon":
            pyshptype = 5
        record.shapeType = pyshptype
        # set points and parts
        if geoj["type"] == "Point":
            record.points = geoj["coordinates"]
            record.parts = [0]
        elif geoj["type"] in ("MultiPoint","Linestring"):
            record.points = geoj["coordinates"]
            record.parts = [0]
        elif geoj["type"] in ("Polygon"):
            record.points = geoj["coordinates"][0]
            record.parts = [0]
        elif geoj["type"] in ("MultiPolygon","MultiLineString"):
            index = 0
            points = []
            parts = []
            for eachmulti in geoj["coordinates"]:
                points.extend(eachmulti[0])
                parts.append(index)
                index += len(eachmulti[0])
            record.points = points
            record.parts = parts
        return record

Simply copy and paste the function to your own script and call on it to convert any of your shapely geometries to a pyshp compatible shape. To save them you then simply append each resulting pyshp shape to the shapefile.Writer instance's ._shapes list (for an example see the test script at the bottom of this post). 

Note however: the function will NOT handle any interior polygon holes if there are any, it simply ignores them. It is certainly possible to add that functionality to the function but I have simply not bothered yet. Suggestions or edits to improve the function are welcome :)

Here is a full standalone test script:

    ### HOW TO SAVE SHAPEFILE FROM SHAPELY GEOMETRY USING PYSHP
    
    # IMPORT STUFF
    import shapefile
    import shapely, shapely.geometry
    
    # CREATE YOUR SHAPELY TEST INPUT
    TEST_SHAPELYSHAPE = shapely.geometry.Polygon([(133,822),(422,644),(223,445),(921,154)])
    
    #########################################################
    ################## END OF USER INPUT ####################
    #########################################################
    
    # DEFINE/COPY-PASTE THE SHAPELY-PYSHP CONVERSION FUNCTION
    def shapely_to_pyshp(shapelygeom):
        # first convert shapely to geojson
        try:
            shapelytogeojson = shapely.geometry.mapping
        except:
            import shapely.geometry
            shapelytogeojson = shapely.geometry.mapping
        geoj = shapelytogeojson(shapelygeom)
        # create empty pyshp shape
        record = shapefile._Shape()
        # set shapetype
        if geoj["type"] == "Null":
            pyshptype = 0
        elif geoj["type"] == "Point":
            pyshptype = 1
        elif geoj["type"] == "LineString":
            pyshptype = 3
        elif geoj["type"] == "Polygon":
            pyshptype = 5
        elif geoj["type"] == "MultiPoint":
            pyshptype = 8
        elif geoj["type"] == "MultiLineString":
            pyshptype = 3
        elif geoj["type"] == "MultiPolygon":
            pyshptype = 5
        record.shapeType = pyshptype
        # set points and parts
        if geoj["type"] == "Point":
            record.points = geoj["coordinates"]
            record.parts = [0]
        elif geoj["type"] in ("MultiPoint","Linestring"):
            record.points = geoj["coordinates"]
            record.parts = [0]
        elif geoj["type"] in ("Polygon"):
            record.points = geoj["coordinates"][0]
            record.parts = [0]
        elif geoj["type"] in ("MultiPolygon","MultiLineString"):
            index = 0
            points = []
            parts = []
            for eachmulti in geoj["coordinates"]:
                points.extend(eachmulti[0])
                parts.append(index)
                index += len(eachmulti[0])
            record.points = points
            record.parts = parts
        return record
    
    # WRITE TO SHAPEFILE USING PYSHP
    shapewriter = shapefile.Writer()
    shapewriter.field("field1")
    # step1: convert shapely to pyshp using the function above
    converted_shape = shapely_to_pyshp(TEST_SHAPELYSHAPE)
    # step2: tell the writer to add the converted shape
    shapewriter._shapes.append(converted_shape)
    # add a list of attributes to go along with the shape
    shapewriter.record(["empty record"])
    # save it
    shapewriter.save("test_shapelytopyshp.shp")


  [1]: https://github.com/karimbahgat/pyshp-fork-speedup-and-geojson-write