The methods you are looking for are gdal.SetProjection() and gdal.SetGeoTranform().
Besides information about the projection, gdal only needs the coordinates of one corner, the size of the pixel and the number of pixels.
name_of_old_tiff = r"C:\path\some.tif"
name_of_new_tiff = r"C:\path\some_projected.tif"
driver = gdal.GetDriverByName('GTiff')
old_tiff = gdal.Open(name_of_old_tiff)
array = old_tiff.GetRasterBand(1).ReadAsArray() #this is a numpy array
projection = """copy/paste the OGC WKT info
for your EPSG as you find it at http://spatialreference.org
Note there are many methods for this, but this way you avoid to import other modules.
if you need automatic way because of many different projections you can look at
this answer https://gis.stackexchange.com/a/193475/98816
bottom_left_x_coo = 288217.9 #use units of projections ie meters
pixel_x_size = 30 #use units of projections ie meters
bottom_left_y_coo = 3638738.602#use units of projections ie meters
pixel_y_size = 30 #use units of projections ie meters
geotransform = (bottom_left_x_coo, pixel_x_size, 0.0, bottom_left_y_coo,0.0, -pixel_y_size)
dtype = gdal.GDT_Int16
# Change data type as needed:
new_tiff = driver.Create(name_of_new_tiff, old_tiff.RasterXSize, old_tiff.RasterYSize, 1, dtype)
new_tiff.GetRasterBand(1).WriteArray(array) #not saved yet
new_tiff = None #remove from memory
Now test it
test = gdal.Open(name_of_new_tiff)
projection_t = test.GetProjection()
geotransform_t = test.GetGeoTransform()